home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Examples / Calc / UCalcCells.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  65.2 KB  |  2,163 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UCalcCells.cp
  3. // Copyright © 1986-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UCALCCELL__
  7. #include "UCalcCells.h"
  8. #endif
  9.  
  10. // Calc
  11.  
  12. #ifndef __UCALC__
  13. #include "UCalc.h"
  14. #endif
  15.  
  16. #ifndef __UCALCCOLUMNS__
  17. #include "UCalcColumns.h"
  18. #endif
  19.  
  20. #ifndef __UCALCROWS__
  21. #include "UCalcRows.h"
  22. #endif
  23.  
  24. // MacApp
  25.  
  26. // Toolbox
  27.  
  28. #ifndef __ERRORS__
  29. #include <Errors.h>
  30. #endif
  31.  
  32. #ifndef __QUICKDRAW__
  33. #include <Quickdraw.h>
  34. #endif
  35.  
  36. // ANSI
  37.  
  38. #ifndef __STDIO__
  39. #include <stdio.h>
  40. #endif
  41.  
  42. #ifndef __STDLIB__
  43. #include <stdlib.h>
  44. #endif
  45.  
  46.  
  47. //========================================================================================
  48. // Global Functions
  49. //========================================================================================
  50. static CompareResult CompareCells(TObject* anItem, void* staticLink);
  51.  
  52. //========================================================================================
  53. // struct CCellComparer
  54. //========================================================================================
  55.  
  56. struct CCellComparer
  57. {
  58. public:
  59.     RowNumber& r;
  60.     ColumnNumber& c;
  61.  
  62.     // Constructor
  63.     CCellComparer(RowNumber& theRow,
  64.                     ColumnNumber& theColumn) :
  65.         r(theRow),
  66.         c(theColumn)
  67.     {
  68.     }
  69. };
  70.  
  71.  
  72. //----------------------------------------------------------------------------------------
  73. // CompareCells: 
  74. //----------------------------------------------------------------------------------------
  75. #pragma segment ARes
  76.  
  77. CompareResult CompareCells(TObject* anItem, void* staticLink)
  78. {
  79.     CCellComparer* comparisonInfo = (CCellComparer*)staticLink;
  80.     
  81.     if (((TCell*)anItem)->fRow > comparisonInfo->r)
  82.         return kItemGreaterThanCriteria;
  83.     else if (((TCell*)anItem)->fRow < comparisonInfo->r)
  84.         return kItemLessThanCriteria;
  85.     else
  86.     {
  87.         if (((TCell*)anItem)->fColumn > comparisonInfo->c)
  88.             return kItemGreaterThanCriteria;
  89.         else if (((TCell*)anItem)->fColumn < comparisonInfo->c)
  90.             return kItemLessThanCriteria;
  91.         else
  92.             return kItemEqualCriteria;
  93.     }
  94. } // CompareCells
  95.  
  96.  
  97. //========================================================================================
  98. // CLASS TCellList
  99. //========================================================================================
  100. #undef Inherited
  101. #define Inherited TList
  102.  
  103. #pragma segment ClassDescRes
  104. MA_DEFINE_CLASS_M1(TCellList, Inherited);
  105.  
  106. //----------------------------------------------------------------------------------------
  107. // TCellList destructor
  108. //----------------------------------------------------------------------------------------
  109. #pragma segment MADestructorRes
  110.  
  111. TCellList::~TCellList()
  112. {
  113. }
  114.  
  115. //----------------------------------------------------------------------------------------
  116. // TCellList::ICellList: 
  117. //----------------------------------------------------------------------------------------
  118. #pragma segment ARes
  119.  
  120. void TCellList::ICellList()
  121. {
  122.     this->ISortedList();
  123. } // TCellList::ICellList 
  124.  
  125.  
  126. //----------------------------------------------------------------------------------------
  127. // TCellList::Compare: 
  128. //----------------------------------------------------------------------------------------
  129. #pragma segment ARes
  130.  
  131. CompareResult TCellList::Compare(TObject* item1,
  132.                                  TObject* item2)    // override 
  133. {
  134.     // since this is a cell list and we make sure that everything in it are cells, we
  135.     // can typecast freely without side effects of insomnia
  136.  
  137.     // row is more important than column when ordering cells
  138.     if (((TCell *)(item1))->fRow > ((TCell *)(item2))->fRow)
  139.         return kItem1GreaterThanItem2;
  140.     else if (((TCell *)(item1))->fRow < ((TCell *)(item2))->fRow)
  141.         return kItem1LessThanItem2;
  142.     else
  143.     {                                            // same row, must check column instead
  144.         if (((TCell *)(item1))->fColumn > ((TCell *)(item2))->fColumn)
  145.             return kItem1GreaterThanItem2;
  146.         else if (((TCell *)(item1))->fColumn < ((TCell *)(item2))->fColumn)
  147.             return kItem1LessThanItem2;
  148.         else
  149.             return kItem1EqualItem2;
  150.     }
  151. } // TCellList::Compare 
  152.  
  153.  
  154. //----------------------------------------------------------------------------------------
  155. // TCellList::GetCell: 
  156. //----------------------------------------------------------------------------------------
  157. #pragma segment ARes
  158.  
  159. TCell* TCellList::GetCell(RowNumber        r,
  160.                           ColumnNumber    c)
  161. {
  162.     CCellComparer aCellComparer(r, c);
  163.     ArrayIndex index;
  164.     
  165.     return (TCell*)this->DoSearch(&::CompareCells, &aCellComparer, index);
  166. } // TCellList::GetCell 
  167.  
  168.  
  169. //========================================================================================
  170. // CLASS TCell
  171. //========================================================================================
  172. #undef Inherited
  173. #define Inherited TObject
  174.  
  175. #pragma segment ClassDescRes
  176. MA_DEFINE_CLASS_M1(TCell, Inherited);
  177.  
  178. //----------------------------------------------------------------------------------------
  179. // TCell constructor 
  180. //----------------------------------------------------------------------------------------
  181. #pragma segment ARes
  182.  
  183. TCell::TCell() :
  184.     fCalcDocument(NULL),
  185.     fDeleted(FALSE),
  186.  
  187.     fKind(kEmptyCell),
  188.     fError(kNoError),
  189.     fValue(0),
  190.  
  191.     fRow(0),
  192.     fColumn(0),
  193.     fEvaluating(FALSE),
  194.  
  195.     fMarked(FALSE)
  196. {
  197.     FailMemError();
  198. } // TCell::TCell 
  199.  
  200.  
  201. //----------------------------------------------------------------------------------------
  202. // TCell::ICell: 
  203. //----------------------------------------------------------------------------------------
  204. #pragma segment ARes
  205.  
  206. void TCell::ICell(TCalcDocument* owningDocument,
  207.                   RowNumber r,
  208.                   ColumnNumber c)
  209.  
  210. {
  211.     this->IObject();
  212.  
  213.     fCalcDocument = owningDocument;
  214.  
  215.     fRow = r;
  216.     fColumn = c;
  217. } // TCell::ICell 
  218.  
  219.  
  220. //----------------------------------------------------------------------------------------
  221. // TCell::Clone: 
  222. //----------------------------------------------------------------------------------------
  223. #pragma segment ARes
  224.  
  225. TObject* TCell::Clone()                // override 
  226.  
  227. {
  228.     TCell * clonedCell;
  229.  
  230.  
  231.     clonedCell = (TCell *)(Inherited::Clone());
  232.     return (TObject *)(clonedCell);
  233. } // TCell::Clone 
  234.  
  235.  
  236. //----------------------------------------------------------------------------------------
  237. // TCell::CopyContents: 
  238. //----------------------------------------------------------------------------------------
  239. #pragma segment ARes
  240.  
  241. void TCell::CopyContents(TCell* sourceCell)
  242.  
  243. {
  244.     fKind = sourceCell->fKind;
  245.     fFormula = sourceCell->fFormula;
  246. } // TCell::CopyContents 
  247.  
  248.  
  249. //----------------------------------------------------------------------------------------
  250. // TCell::Free: 
  251. //----------------------------------------------------------------------------------------
  252. #pragma segment ARes
  253.  
  254. TCell::~TCell()
  255.  
  256. {
  257. } // TCell::Free 
  258.  
  259.  
  260. //----------------------------------------------------------------------------------------
  261. // TCell::EvaluateFormula: 
  262. //----------------------------------------------------------------------------------------
  263. #pragma segment ARes
  264.  
  265. void TCell::EvaluateFormula(Boolean    updateDependencies, Boolean& cellChanged)
  266.  
  267. {
  268.     KindOfCell    theKind = kEmptyCell;
  269.     EvalResult    theError = kNoError;
  270.     ValueType    theValue = 0;
  271.  
  272.     if (updateDependencies)
  273.     {
  274.         // Use nesting to conserve stack space -- the iterator is destroyed before
  275.         // we get here, so the parser and CStr255 can be allocated in its place!!
  276.  
  277.         CReferencedCellIterator iter(this);
  278.         for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  279.             aCell->RemoveDependentCell(this);
  280.     }
  281.  
  282.     fValueString.Empty();
  283.  
  284.     fEvaluating = TRUE;                            // prevent self reference loop 
  285.  
  286.     {                                            // Use nesting to conserve stack space --
  287.                                                 // the iterator is destroyed before we get
  288.                                                 // here, so the parser can be allocated in
  289.                                                 // its place!!
  290.         CCellParser theParser(this);
  291.  
  292.         theParser.EvaluateFormula(theKind, theError, theValue, fFormula, updateDependencies);
  293.     }
  294.  
  295.     fEvaluating = FALSE;
  296.  
  297.     cellChanged = (theValue != fValue) || (theKind != fKind);
  298.     if (cellChanged)
  299.     {
  300.         fCalcDocument->SetChangeCount(Max(fCalcDocument->fChangeCount + 1, 1));
  301.         if ((theError == kNoError) || (theError == kGarbageAtEnd))
  302.             fValue = theValue;
  303.         fKind = theKind;
  304.         this->invalidate();
  305.     }
  306. } // TCell::EvaluateFormula 
  307.  
  308.  
  309. //----------------------------------------------------------------------------------------
  310. // TCell::GetAsString: 
  311. //----------------------------------------------------------------------------------------
  312. #pragma segment ARes
  313.  
  314. void TCell::GetAsString(CStr255& theString)
  315.  
  316. {
  317.     theString = fFormula;
  318. } // TCell::GetAsString 
  319.  
  320.  
  321. //----------------------------------------------------------------------------------------
  322. // TCell::GetValueAsString: 
  323. //----------------------------------------------------------------------------------------
  324. #pragma segment ARes
  325.  
  326. void TCell::GetValueAsString(CStr255& theString)
  327.  
  328. {
  329.     theString.Empty();
  330.     switch (fKind)
  331.     {
  332.         case kTextCell:
  333.             theString = fFormula;
  334.             break;
  335.  
  336.         case kValueCell:
  337.             if (fValueString.IsEmpty())
  338.                 this->ValueToString();
  339.             theString = fValueString;
  340.             break;
  341.  
  342.         case kErrorCell:
  343.             NumToString(fError, theString);
  344.             theString = "**ERROR " + theString;
  345.             break;
  346.  
  347.     }
  348. } // TCell::GetValueAsString 
  349.  
  350.  
  351. //----------------------------------------------------------------------------------------
  352. // TCell::GetCoordinates:  Returns a CPoint describing the Cell's location on the GridView
  353. //----------------------------------------------------------------------------------------
  354. #pragma segment ARes
  355.  
  356. CPoint TCell::GetCoordinates()
  357. {
  358.     return CPoint(fColumn, fRow);
  359. } // TCell::GetCoordinates 
  360.  
  361.  
  362. //----------------------------------------------------------------------------------------
  363. // TCell::invalidate: 
  364. //----------------------------------------------------------------------------------------
  365. #pragma segment ARes
  366.  
  367. void TCell::invalidate()
  368. {
  369.     GridCell aCell;
  370.  
  371.  
  372.     if ((fCalcDocument != NULL) && (fCalcDocument->fCellsView != NULL))
  373.     {
  374.         aCell.h = fColumn;
  375.         aCell.v = fRow;
  376.         fCalcDocument->fCellsView->InvalidateCell(aCell);
  377.     }
  378. } // TCell::invalidate 
  379.  
  380.  
  381. //----------------------------------------------------------------------------------------
  382. // TCell::IsEmpty: 
  383. //----------------------------------------------------------------------------------------
  384. #pragma segment ARes
  385.  
  386. Boolean TCell::IsEmpty()
  387.  
  388. {
  389.     return (fKind == kEmptyCell) && (fFormula.Length() == 0);
  390. } // TCell::IsEmpty 
  391.  
  392.  
  393. //----------------------------------------------------------------------------------------
  394. // TCell::SetDeleteState: 
  395. //----------------------------------------------------------------------------------------
  396. #pragma segment ARes
  397.  
  398. void TCell::SetDeleteState(Boolean deleted)
  399.  
  400. {
  401.     fDeleted = deleted;
  402. } // TCell::SetDeleteState 
  403.  
  404.  
  405. //----------------------------------------------------------------------------------------
  406. // TCell::SetToString: 
  407. //----------------------------------------------------------------------------------------
  408. #pragma segment ARes
  409.  
  410. void TCell::SetToString(const CStr255& theString)
  411.  
  412. {
  413.     CStr255 theOldString;
  414.  
  415.     this->GetAsString(theOldString);
  416.     if (CompareStrings(theString, theOldString) != 0)
  417.     {
  418.         fFormula = theString;
  419.         fKind = kEmptyCell;                        // Force Recalculate to invalidate the cell 
  420.         this->Recalculate(!kForceAutomatic, kUpdateDependencies);// we want to set new dependents 
  421.  
  422.         //!!!RCR Changed(0, fCalcDocument);
  423.     }
  424. } // TCell::SetToString 
  425.  
  426.  
  427. //----------------------------------------------------------------------------------------
  428. // TCell::Recalculate: 
  429. //----------------------------------------------------------------------------------------
  430. #pragma segment ARes
  431.  
  432. void TCell::Recalculate(Boolean forceAutomatic, Boolean updateDependencies)
  433.  
  434. {
  435.     Boolean cellChanged;
  436.  
  437.     this->EvaluateFormula(updateDependencies, cellChanged);
  438.     if (cellChanged && (forceAutomatic || fCalcDocument->IsAutoCalc()))
  439.         this->Changed(mValueChanged, this);
  440. } // TCell::Recalculate 
  441.  
  442. //----------------------------------------------------------------------------------------
  443. // TCell::GetDependencySpace: 
  444. //----------------------------------------------------------------------------------------
  445. #pragma segment ARes
  446.  
  447. TDependencySpace* TCell::GetDependencySpace()    // Override
  448.  
  449. {
  450.     return fCalcDocument->fDependencies;
  451. } // TCell::GetDependencySpace 
  452.  
  453. //----------------------------------------------------------------------------------------
  454. // TCell::DoUpdate: 
  455. //----------------------------------------------------------------------------------------
  456. #pragma segment ARes
  457. void TCell::DoUpdate(ChangeID theChange,
  458.                      TObject* changedObject,
  459.                      TObject* changedBy,
  460.                      TDependencySpace* dependencySpace)    // override 
  461.  
  462. {
  463.     Boolean cellChanged;
  464.     
  465.     if (theChange == mValueChanged)
  466.     {
  467.         this->EvaluateFormula(!kUpdateDependencies, cellChanged);
  468.         if (!cellChanged)
  469.             theChange = kNoChange;
  470.     }
  471.     else if (theChange == mWidthChanged)
  472.         theChange = kNoChange;
  473.     else
  474.         Inherited::DoUpdate(theChange, changedObject, changedBy, dependencySpace);
  475. } // TCell::DoUpdate 
  476.  
  477.  
  478. //----------------------------------------------------------------------------------------
  479. // TCell::GetNoOfDependentCells: 
  480. //----------------------------------------------------------------------------------------
  481. #pragma segment ARes
  482. ArrayIndex TCell::GetNoOfDependentCells()
  483.  
  484. {
  485.     ArrayIndex                count = 0;
  486.     CDependentCellIterator    iter(this);
  487.  
  488.     for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  489.     {
  490.         count = count + 1;
  491.     }
  492.  
  493.     return count;
  494. } // TCell::GetNoOfDependentCells 
  495.  
  496.  
  497. //----------------------------------------------------------------------------------------
  498. // TCell::GetNoOfReferencedCells: 
  499. //----------------------------------------------------------------------------------------
  500. #pragma segment ARes
  501. ArrayIndex TCell::GetNoOfReferencedCells()
  502.  
  503. {
  504.     ArrayIndex                count = 0;
  505.     CReferencedCellIterator    iter(this);
  506.  
  507.     for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  508.     {
  509.         count = count + 1;
  510.     }
  511.  
  512.     return count;
  513. } // TCell::GetNoOfReferencedCells 
  514.  
  515.  
  516. //----------------------------------------------------------------------------------------
  517. // TCell::AddDependentCell: 
  518. //----------------------------------------------------------------------------------------
  519. #pragma segment ARes
  520.  
  521. void TCell::AddDependentCell(TCell* aCell)
  522. {
  523.     this->AddDependent(aCell);
  524. } // TCell::AddDependentCell 
  525.  
  526.  
  527. //----------------------------------------------------------------------------------------
  528. // TCell::RemoveDependentCell: 
  529. //----------------------------------------------------------------------------------------
  530. #pragma segment ARes
  531.  
  532. void TCell::RemoveDependentCell(TCell* aCell)
  533. {
  534.     this->RemoveDependent(aCell);
  535. } // TCell::RemoveDependentCell 
  536.  
  537.  
  538. //----------------------------------------------------------------------------------------
  539. // TCell::ValueToString: Fills fValueString with the CString representation of the cell's
  540. // value. The "general" format is complicated because we try to ensure that the CString
  541. // will fit within the cell's column width. Thus we have to figure out the appropriate
  542. // representation for the value.
  543. //----------------------------------------------------------------------------------------
  544. #pragma segment ARes
  545.  
  546. void TCell::ValueToString()
  547. {
  548.     CStr255        aString;
  549.     char        aCString[255];                        // a char* type with preallocated 
  550.                                                     // space.  Used for a temp value later;
  551.     decform        theFormat;
  552.     decimal        d;
  553.     decimal        aDecimal;
  554.     short        i;
  555.     short        len;
  556.     short        sigDigits;
  557.     short        leftDigits;
  558.     short        rightDigits;
  559.     short        width;
  560.     short        digitWidth;
  561.     short        dotWidth;
  562.     short        eWidth;
  563.     short        minusWidth;
  564.     short        plusWidth;
  565.     TColumn *    aColumn;
  566.     ValueType    aValueType;
  567.  
  568.  
  569.     aColumn = fCalcDocument->GetColumn(fColumn);
  570.  
  571.     switch (aColumn->fFormat.fStyle)
  572.     {
  573.         case kGeneral:
  574.             {
  575.                 SetTheFont(aColumn->fFormat.fFontNumber, aColumn->fFormat.fFontSize, aColumn->fFormat.fFontStyle);
  576.                 digitWidth = CharWidth('0');
  577.                 dotWidth = CharWidth('.');
  578.                 eWidth = CharWidth('e');
  579.                 minusWidth = CharWidth('-');
  580.                 plusWidth = CharWidth('+');
  581.                 width = fCalcDocument->fCellsView->GetColWidth(fColumn) - (kCellHBorder * 2);
  582.  
  583.                 theFormat = gGeneralFormat;
  584.                 aValueType = fValue;
  585.                 num2dec(&theFormat, aValueType, &d);
  586.                 aString = *((CStr255 *)(&d.sig));// sig is actually a CString, and we want it!
  587.  
  588.                 len = aString.Length();
  589.  
  590.                 if (d.sgn == 1)
  591.                     width = width - minusWidth;
  592.  
  593.                 if (d.exp > 0)
  594.                 // We've exceeded the precision of our value representation 
  595.                 {
  596.                     theFormat.style = FLOATDECIMAL;
  597.                     // account for '.' and '+e99' 
  598.                     width = width - dotWidth - CharWidth('+') - eWidth - digitWidth - digitWidth;
  599.                     theFormat.digits = Min(kValuePrecision, width / digitWidth);
  600.                 }
  601.                 else
  602.                 {
  603.  
  604.                     // determine number of significant digits 
  605.                     sigDigits = 1;                // in case all digits are zero 
  606.                     for (i = len; i >= 2; i--)    // this was DOWNTO
  607.                         if (aString[i] != '0')
  608.                         {
  609.                             sigDigits = i;
  610.                             break;
  611.                         }
  612.  
  613.                     leftDigits = kValuePrecision + d.exp;
  614.                     rightDigits = sigDigits - leftDigits;
  615.  
  616.                     if (leftDigits < sigDigits)
  617.                         width = width - dotWidth;// account for decimal CPoint 
  618.  
  619.                     if (leftDigits * digitWidth > width)
  620.                     {
  621.                         // We must convert to scientific notation 
  622.  
  623.                         // account for decimal CPoint and 'e9' 
  624.                         width = width - dotWidth - eWidth - digitWidth;
  625.  
  626.                         /* For positive numbers, SANE puts a space (' ') before
  627.                           the first significant digit. */
  628.                         if (d.sgn != 1)
  629.                             width = width - CharWidth(' ');
  630.                         if (d.exp < -kValuePrecision)
  631.                             width = width - minusWidth;
  632.                         else
  633.                             width = width - plusWidth;
  634.                         if (leftDigits > 10)
  635.                             width = width - digitWidth;// account for double-digit exponents 
  636.  
  637.                         theFormat.style = FLOATDECIMAL;
  638.                         theFormat.digits = Min(sigDigits, width / digitWidth);
  639.                     }
  640.                     else
  641.                     {
  642.                         theFormat.style = FIXEDDECIMAL;
  643.                         theFormat.digits = Min((width - (leftDigits * digitWidth) - dotWidth) / digitWidth, rightDigits);
  644.                         if (theFormat.digits < 0)
  645.                             theFormat.digits = 0;
  646.                     }
  647.                 }
  648.                 break;
  649.             }
  650.         case kDecimalStyle:
  651.             {
  652.                 theFormat = gDecimalFormat;
  653.                 break;
  654.             }
  655.         case kNoDecimal:
  656.             {
  657.                 theFormat = gNoDecimalFormat;
  658.                 break;
  659.             }
  660.         case kScientific:
  661.             {
  662.                 theFormat = gScientificFormat;
  663.                 break;
  664.             }
  665.     }                                            // switch!
  666.  
  667.     aValueType = fValue;
  668.     num2dec(&theFormat, aValueType, &aDecimal);
  669.     dec2str(&theFormat, &aDecimal, aCString);
  670.     aString = aCString;
  671.     //  That should have been "Num2Str(theFormat, aValueType, (decstr)(aString));"
  672.     if (aString[1] == ' ')
  673.         aString.Delete(1, 1);                    // Remove leading space 
  674.     fValueString = aString.Copy(1, Min(kMaxValueLength, aString.Length()));
  675. } // TCell::ValueToString 
  676.  
  677.  
  678. //----------------------------------------------------------------------------------------
  679. // TCell::GetDiskSize: 
  680. //----------------------------------------------------------------------------------------
  681. #pragma segment AWriteFile
  682.  
  683. short TCell::GetDiskSize(Boolean infoRecordOnly)
  684.  
  685. {
  686.     short cellSize;
  687.  
  688.  
  689.     cellSize = sizeof(CellDiskInfo) - sizeof(CStr255) + fFormula.Length() + 1;
  690.     if (!infoRecordOnly)
  691.         cellSize = cellSize + (short)(this->GetNoOfReferencedCells() + this->GetNoOfDependentCells() + 1) * sizeof(CPoint);
  692.     return cellSize;
  693. } // TCell::GetDiskSize 
  694.  
  695.  
  696. //----------------------------------------------------------------------------------------
  697. // TCell::ReadFromDisk: 
  698. //----------------------------------------------------------------------------------------
  699. #pragma segment AReadFile
  700.  
  701. void TCell::ReadFromDisk(TFile* aFile)
  702. {
  703.     CellDiskInfo    cellInfo;
  704.     TCell *            referencedCell;
  705.     RowNumber        refRow;
  706.     ColumnNumber    refColumn;
  707.     short            refIndex;
  708.     long            count;
  709.     short            cellLength;
  710.  
  711.     count = sizeof(cellLength);
  712.     FailOSErr(aFile->ReadData(&cellLength, count));
  713.     count = cellLength;
  714.     FailOSErr(aFile->ReadData(&cellInfo, count));
  715.  
  716.     fKind = cellInfo.kind;
  717.     fError = cellInfo.error;
  718.     fValue = cellInfo.value;
  719.     fFormula = cellInfo.formula;
  720.  
  721.     for (refIndex = 1; refIndex <= cellInfo.noOfReferences; refIndex++)
  722.     {
  723.         ReadCellCoordinate(aFile, refRow, refColumn);
  724.         referencedCell = fCalcDocument->GetCell(refRow, refColumn);
  725.         referencedCell->AddDependentCell(this);
  726.     }
  727. } // TCell::ReadFromDisk 
  728.  
  729.  
  730. //----------------------------------------------------------------------------------------
  731. // TCell::WriteToDisk: 
  732. //----------------------------------------------------------------------------------------
  733. #pragma segment AWriteFile
  734.  
  735. void TCell::WriteToDisk(TFile* aFile)
  736. {
  737.     CellDiskInfo    cellInfo;
  738.     long            count;
  739.     short            cellLength;
  740.  
  741.     // write out the data that TCalcDocument.DoRead expects to see 
  742.     this->WriteCellCoordinateToDisk(aFile);
  743.  
  744.     cellLength = this->GetDiskSize(TRUE);
  745.     count = sizeof(cellLength);
  746.     FailOSErr(aFile->WriteData(&cellLength, count));
  747.  
  748.     // write out the data that TCell.ReadFromDisk expects to see 
  749.     cellInfo.kind = fKind;
  750.     cellInfo.error = fError;
  751.     cellInfo.value = fValue;
  752.     cellInfo.noOfReferences = (short)this->GetNoOfReferencedCells();
  753.     cellInfo.formula = fFormula;
  754.     count = cellLength;
  755.     FailOSErr(aFile->WriteData(&cellInfo, count));
  756.  
  757.     CReferencedCellIterator iter(this);
  758.  
  759.     for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  760.         aCell->WriteCellCoordinateToDisk(aFile);
  761. } // TCell::WriteToDisk 
  762.  
  763.  
  764. //----------------------------------------------------------------------------------------
  765. // TCell::WriteCellCoordinateToDisk: 
  766. //----------------------------------------------------------------------------------------
  767. #pragma segment AWriteFile
  768.  
  769. void TCell::WriteCellCoordinateToDisk(TFile* aFile)
  770. {
  771.     CPoint    cellCoordinate;
  772.     long    count;
  773.  
  774.     cellCoordinate.v = this->fRow;
  775.     cellCoordinate.h = this->fColumn;
  776.     count = sizeof(CPoint);
  777.     FailOSErr(aFile->WriteData(&cellCoordinate, count));
  778. } // TCell::WriteCellCoordinateToDisk 
  779.  
  780.  
  781. //----------------------------------------------------------------------------------------
  782. // TCell::ReadFromScrap: 
  783. //----------------------------------------------------------------------------------------
  784. #pragma segment AClipBoard
  785.  
  786. void TCell::ReadFromScrap(Handle theScrap, long&    scrapOffset)
  787.  
  788. {
  789.     short            cellLength;
  790.     CellDiskInfo    cellInfo;
  791.     TCell *            referencedCell;
  792.     CPoint            cellCoord;
  793.     short            refIndex;
  794.  
  795.  
  796.     ReadScrap(theScrap, scrapOffset, (unsigned char*) & cellLength, sizeof(cellLength));
  797.     ReadScrap(theScrap, scrapOffset, (unsigned char*) & cellInfo, cellLength);
  798.  
  799.     fKind = cellInfo.kind;
  800.     fError = cellInfo.error;
  801.     fValue = cellInfo.value;
  802.     fFormula = cellInfo.formula;
  803.  
  804.     for (refIndex = 1; refIndex <= cellInfo.noOfReferences; refIndex++)
  805.     {
  806.         ReadScrap(theScrap, scrapOffset, (unsigned char*) & cellCoord, sizeof(cellCoord));
  807.         referencedCell = fCalcDocument->GetCell(cellCoord.v, cellCoord.h);
  808.         referencedCell->AddDependentCell(this);
  809.     }
  810. } // TCell::ReadFromScrap 
  811.  
  812.  
  813. //----------------------------------------------------------------------------------------
  814. // TCell::WriteToScrap: 
  815. //----------------------------------------------------------------------------------------
  816. #pragma segment AClipBoard
  817.  
  818. void TCell::WriteToScrap(Handle    theScrap, long&    scrapOffset)
  819.  
  820. {
  821.     CellDiskInfo    cellInfo;
  822.     short            cellLength;
  823.     CPoint            cellCoordinate;
  824.  
  825.  
  826.     cellCoordinate.v = this->fRow;
  827.     cellCoordinate.h = this->fColumn;
  828.     WriteScrap(theScrap, scrapOffset, (unsigned char*) & cellCoordinate, sizeof(cellCoordinate));
  829.  
  830.     cellLength = GetDiskSize(TRUE);                // don't include ref's && dependents 
  831.     WriteScrap(theScrap, scrapOffset, (unsigned char*) & cellLength, sizeof(cellLength));
  832.     cellInfo.kind = fKind;
  833.     cellInfo.error = fError;
  834.     cellInfo.value = fValue;
  835.     cellInfo.noOfReferences = 0;
  836.     cellInfo.formula = fFormula;
  837.  
  838.     WriteScrap(theScrap, scrapOffset, (unsigned char*) & cellInfo, cellLength);
  839. } // TCell::WriteToScrap 
  840.  
  841.  
  842. //========================================================================================
  843. // CLASS TCellEditCommand
  844. //========================================================================================
  845. #undef Inherited
  846. #define Inherited TCommand
  847.  
  848. #pragma segment ClassDescRes
  849. MA_DEFINE_CLASS_M1(TCellEditCommand, Inherited);
  850.  
  851. //----------------------------------------------------------------------------------------
  852. // TCellEditCommand::ICellEditCommand: 
  853. //----------------------------------------------------------------------------------------
  854. #pragma segment ASelCommand
  855.  
  856. void TCellEditCommand::ICellEditCommand(TCalcDocument*    itsDocument,
  857.                                         CommandNumber    itsCommand)
  858.  
  859. {
  860.     this->ICommand(itsCommand, itsDocument, kCanUndo, kCausesChange, itsDocument);
  861.     FailInfo fi;
  862.     Try(fi)
  863.     {
  864.         fCalcDocument = itsDocument;
  865.         fSelection = MakeNewRgn();                    // copy the current selection region 
  866.         CopyRgn(itsDocument->fCellsView->fSelections, fSelection);
  867.         fChangesClipboard = itsCommand != cClear;
  868.         fCausesChange = itsCommand != cCopy;
  869.         fi.Success();
  870.     }
  871.     else
  872.     {
  873.         this->Free();
  874.         fi.ReSignal();
  875.     }
  876. } // TCellEditCommand::ICellEditCommand 
  877.  
  878.  
  879. //----------------------------------------------------------------------------------------
  880. // TCellEditCommand::Free: 
  881. //----------------------------------------------------------------------------------------
  882. #pragma segment ARes
  883.  
  884. TCellEditCommand::~TCellEditCommand()        // override 
  885.  
  886. {
  887.     fSelection = DisposeIfRgnHandle(fSelection);
  888. } // TCellEditCommand::Free 
  889.  
  890.  
  891. //----------------------------------------------------------------------------------------
  892. // TCellEditCommand::DoIt: 
  893. //----------------------------------------------------------------------------------------
  894. #pragma segment ADoCommand
  895.  
  896. void TCellEditCommand::DoIt()
  897.  
  898. {
  899.     if (fIdentifier != cClear)
  900.         this->CopySelection();
  901.     if (fIdentifier != cCopy)
  902.         this->DeleteSelection();
  903. } // TCellEditCommand::DoIt 
  904.  
  905.  
  906. //----------------------------------------------------------------------------------------
  907. // TCellEditCommand::UndoIt: If the user has changed the selection since this command was
  908. // created, restore it before Undoing so that the correct cells are affected.
  909. //----------------------------------------------------------------------------------------
  910. #pragma segment ADoCommand
  911.  
  912. void TCellEditCommand::UndoIt()
  913. {
  914.     if (fIdentifier != cCopy)
  915.     {
  916.         this->ReSelect();                        // restore command's original selection 
  917.         this->RestoreSelection();
  918.         fCalcDocument->fCellsView->ScrollSelectionIntoView(TRUE);
  919.     }
  920. } // TCellEditCommand::UndoIt 
  921.  
  922.  
  923. //----------------------------------------------------------------------------------------
  924. // TCellEditCommand::RedoIt: If the user has changed the selection since this command was
  925. // created, restore it before Redoing so that the correct cells are affected.
  926. //----------------------------------------------------------------------------------------
  927. #pragma segment ADoCommand
  928.  
  929. void TCellEditCommand::RedoIt()
  930. {
  931.     if (fIdentifier != cCopy)
  932.     {
  933.         this->ReSelect();                        // restore command's original selection 
  934.         this->DeleteSelection();
  935.         fCalcDocument->fCellsView->ScrollSelectionIntoView(TRUE);
  936.     }
  937. } // TCellEditCommand::RedoIt 
  938.  
  939.  
  940. //----------------------------------------------------------------------------------------
  941. // TCellEditCommand::Commit: 
  942. //----------------------------------------------------------------------------------------
  943. #pragma segment ADoCommand
  944.  
  945. void TCellEditCommand::Commit()
  946.  
  947. {
  948.     fCalcDocument->FreeDeletedCells();
  949. } // TCellEditCommand::Commit 
  950.  
  951.  
  952. //----------------------------------------------------------------------------------------
  953. // TCellEditCommand::CopySelection: 
  954. //----------------------------------------------------------------------------------------
  955. #pragma segment ADoCommand
  956.  
  957. void TCellEditCommand::CopySelection()
  958.  
  959. {
  960.     TCalcDocument *    clipDocument;
  961.     TCellsView *    clipView;
  962.     CRect            clipRect;
  963.  
  964.     clipDocument = new TCalcDocument;
  965.     clipRect = (*fSelection)->rgnBBox;
  966.     clipRect.bottom = clipRect.bottom - 1;
  967.     clipRect.right = clipRect.right - 1;
  968.     clipDocument->ICalcDocument(NULL, clipRect);
  969.     clipDocument->DoInitialState();
  970.  
  971.     {
  972.         CSelectedCellIterator iter(fCalcDocument->fRowsView);
  973.         for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  974.         {
  975.             TRow * newRow;
  976.  
  977.  
  978.             newRow = (TRow *)(fCalcDocument->GetRow(aCell.v)->Clone());
  979.             newRow->fNumber = newRow->fNumber - clipDocument->fRowOffset;
  980.             clipDocument->AddRow(newRow);
  981.         }
  982.     }
  983.  
  984.     {
  985.         CSelectedCellIterator iter(fCalcDocument->fColumnsView);
  986.         for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  987.         {
  988.             TColumn * newColumn;
  989.  
  990.  
  991.             newColumn = (TColumn *)(fCalcDocument->GetColumn(aCell.h)->Clone());
  992.             newColumn->fNumber = newColumn->fNumber - clipDocument->fColumnOffset;
  993.             clipDocument->AddColumn(newColumn);
  994.         }
  995.     }
  996.  
  997.     {
  998.         CSelectedExistingCalcCellIterator iter(fCalcDocument);
  999.         for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1000.         {
  1001.             TCell * newCell;
  1002.             newCell = (TCell *)(aCell->Clone());
  1003.             clipDocument->AddCell(newCell, newCell->fRow - clipDocument->fRowOffset, newCell->fColumn - clipDocument->fColumnOffset);
  1004.         }
  1005.     }
  1006.  
  1007.     clipView = new TCellsView;
  1008.     clipView->ICellsView(clipDocument, TRUE, NULL);
  1009.     clipDocument->fCellsView = clipView;
  1010.     this->ClaimClipboard(clipView);
  1011.     clipView->AdjustFrame();
  1012. } // TCellEditCommand::CopySelection 
  1013.  
  1014.  
  1015. //----------------------------------------------------------------------------------------
  1016. // TCellEditCommand::DeleteSelection: 
  1017. //----------------------------------------------------------------------------------------
  1018. #pragma segment ADoCommand
  1019.  
  1020. void TCellEditCommand::DeleteSelection()
  1021. {
  1022.     CSelectedExistingCalcCellIterator iter(fCalcDocument);
  1023.     
  1024.     for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1025.     {
  1026.         fCalcDocument->DeleteCell(aCell->fRow, aCell->fColumn);
  1027.     }
  1028.  
  1029.     fCalcDocument->DoRecalculate(!kForceAutomatic, !kUpdateDependencies);
  1030.     fCalcDocument->fCellsView->InvalidateSelection();
  1031. } // TCellEditCommand::DeleteSelection 
  1032.  
  1033.  
  1034. //----------------------------------------------------------------------------------------
  1035. // TCellEditCommand::RestoreSelection: 
  1036. //----------------------------------------------------------------------------------------
  1037. #pragma segment ADoCommand
  1038.  
  1039. void TCellEditCommand::RestoreSelection()
  1040.  
  1041. {
  1042.     GridCell                            firstCell;
  1043.     CSelectedExistingCalcCellIterator    iter(fCalcDocument);
  1044.  
  1045.     for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1046.     {
  1047.         fCalcDocument->UndeleteCell(aCell->fRow, aCell->fColumn);
  1048.     }
  1049.  
  1050.     fCalcDocument->DoRecalculate(!kForceAutomatic, !kUpdateDependencies);
  1051.     fCalcDocument->fCellsView->InvalidateSelection();
  1052.  
  1053.     firstCell = fCalcDocument->fCellsView->FirstSelectedCell();
  1054.     fCalcDocument->SetEntry(firstCell.v, firstCell.h);// update entry view 
  1055. } // TCellEditCommand::RestoreSelection 
  1056.  
  1057.  
  1058. //----------------------------------------------------------------------------------------
  1059. // TCellEditCommand::ReSelect: 
  1060. //----------------------------------------------------------------------------------------
  1061. #pragma segment ADoCommand
  1062.  
  1063. void TCellEditCommand::ReSelect()
  1064.  
  1065. {
  1066.     fCalcDocument->fCellsView->ReSelect(fSelection);
  1067. } // TCellEditCommand::ReSelect 
  1068.  
  1069.  
  1070. //========================================================================================
  1071. // CLASS TCellPasteCommand
  1072. //========================================================================================
  1073. #undef Inherited
  1074. #define Inherited TCommand
  1075.  
  1076. #pragma segment ClassDescRes
  1077. MA_DEFINE_CLASS_M1(TCellPasteCommand, Inherited);
  1078.  
  1079. //----------------------------------------------------------------------------------------
  1080. // TCellPasteCommand::ICellPasteCommand: 
  1081. //----------------------------------------------------------------------------------------
  1082. #pragma segment ASelCommand
  1083.  
  1084. void TCellPasteCommand::ICellPasteCommand(TCalcDocument* itsDocument)
  1085. {
  1086. #if qDebug
  1087.     if (!(gClipboardMgr->fClipView->DescendsFrom(TCellsView::GetClassDescStatic())))
  1088.         ProgramBreak("Attempt to paste a non-TCellsView clipboard");
  1089. #endif
  1090.  
  1091.     this->ICommand(cPaste, itsDocument, kCanUndo, kCausesChange, itsDocument);
  1092.  
  1093.     FailInfo fi;
  1094.     Try(fi)
  1095.     {
  1096.         fCalcDocument = itsDocument;
  1097.         fSelection = MakeNewRgn();                    // copy the current selection region 
  1098.         CopyRgn(itsDocument->fCellsView->fSelections, fSelection);
  1099.         fClipDocument = ((TCellsView *)(gClipboardMgr->fClipView))->fCalcDocument;
  1100.         fReplacedCells = (TCellList *)NewList();
  1101. #if qDebug
  1102.         fReplacedCells->SetEltType("TCell");
  1103. #endif
  1104.         fi.Success();
  1105.     }
  1106.     else
  1107.     {
  1108.         this->Free();
  1109.         fi.ReSignal();
  1110.     }
  1111. } // TCellPasteCommand::ICellPasteCommand 
  1112.  
  1113.  
  1114. //----------------------------------------------------------------------------------------
  1115. // TCellPasteCommand::Free: 
  1116. //----------------------------------------------------------------------------------------
  1117. #pragma segment ADoCommand
  1118.  
  1119. TCellPasteCommand::~TCellPasteCommand()        // override 
  1120.  
  1121. {
  1122.     fSelection = DisposeIfRgnHandle(fSelection);
  1123.  
  1124.     fReplacedCells = (TCellList *)(FreeListIfObject(fReplacedCells));
  1125. } // TCellPasteCommand::Free 
  1126.  
  1127.  
  1128. //----------------------------------------------------------------------------------------
  1129. // TCellPasteCommand::DoIt: 
  1130. //----------------------------------------------------------------------------------------
  1131. #pragma segment ADoCommand
  1132.  
  1133. void TCellPasteCommand::DoIt()
  1134. {
  1135.     FailInfo fi;
  1136.  
  1137.     Try(fi)
  1138.     {
  1139.         short r = 1;
  1140.         short c = 1;
  1141.         
  1142.         // Extra block to ensure that Success is called in the proper order
  1143.         {
  1144.             CSelectedCellIterator iter(fCalcDocument->fCellsView);
  1145.         
  1146.             for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1147.             {
  1148.                 TCell* sourceCell;
  1149.                 TCell* replacedCell;
  1150.                 TCell* destCell;
  1151.                 
  1152.                 destCell = fCalcDocument->GetCell(aCell.v, aCell.h);
  1153.                 replacedCell = (TCell *)(destCell->Clone());
  1154.                 fReplacedCells->InsertLast(replacedCell);
  1155.             
  1156.                 sourceCell = fClipDocument->GetCell(r, c);
  1157.                 ++c;
  1158.                 if (c > fClipDocument->fNoOfColumns)
  1159.                 {
  1160.                     c = 1;
  1161.                     ++r;
  1162.                     if (r > fClipDocument->fNoOfRows)
  1163.                         r = 1;
  1164.                 }
  1165.                 destCell->CopyContents(sourceCell);            // copy the necessary fields 
  1166.             }
  1167.         }
  1168.         fi.Success();
  1169.     }
  1170.     else
  1171.     {
  1172.         // Extra block to ensure that ReSignal is called in the proper order
  1173.         {
  1174.             CCalcCellIterator iter(fReplacedCells);
  1175.         
  1176.             for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1177.             {
  1178.                 TCell*    pastedCell;
  1179.             
  1180.                 pastedCell = fCalcDocument->GetCell(aCell->fRow, aCell->fColumn);
  1181.                 if (aCell->IsEmpty())                                    // free up memory used by empty cell 
  1182.                 {
  1183.                     fCalcDocument->DeleteCell(pastedCell->fRow, pastedCell->fColumn);
  1184.                     fCalcDocument->FreeCell(pastedCell);
  1185.                 }            
  1186.                 else
  1187.                     pastedCell->CopyContents(aCell);
  1188.             }
  1189.         }
  1190.         fReplacedCells->FreeAll();
  1191.         this->UpdateViews();
  1192.         fi.ReSignal();
  1193.     }
  1194.  
  1195.     this->UpdateViews();
  1196. } // TCellPasteCommand::DoIt 
  1197.  
  1198.  
  1199. //----------------------------------------------------------------------------------------
  1200. // TCellPasteCommand::UndoIt: 
  1201. //----------------------------------------------------------------------------------------
  1202. #pragma segment ADoCommand
  1203.  
  1204. void TCellPasteCommand::UndoIt()
  1205. {
  1206.     CCalcCellIterator iter(fReplacedCells);
  1207.  
  1208.     fCalcDocument->fCellsView->ReSelect(fSelection);// restore original selection 
  1209.     for (TCell * replacedCell = iter.FirstCell(); iter.More(); replacedCell = iter.NextCell())
  1210.     {
  1211.         TCell * pastedCell;
  1212.  
  1213.         pastedCell = fCalcDocument->GetCell(replacedCell->fRow, replacedCell->fColumn);
  1214.         pastedCell->CopyContents(replacedCell);
  1215.     }
  1216.     this->UpdateViews();
  1217. } // TCellPasteCommand::UndoIt 
  1218.  
  1219.  
  1220. //----------------------------------------------------------------------------------------
  1221. // TCellPasteCommand::RedoIt: 
  1222. //----------------------------------------------------------------------------------------
  1223. #pragma segment ADoCommand
  1224.  
  1225. void TCellPasteCommand::RedoIt()
  1226. {
  1227.     short r = 1;
  1228.     short c = 1;
  1229.     
  1230.     fCalcDocument->fCellsView->ReSelect(fSelection);// restore original selection
  1231.     
  1232.     CSelectedCellIterator iter(fCalcDocument->fCellsView);
  1233.  
  1234.     for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1235.     {
  1236.         TCell * sourceCell;
  1237.         TCell * destCell;
  1238.         
  1239.         destCell = fCalcDocument->GetCell(aCell.v, aCell.h);
  1240.         sourceCell = fClipDocument->GetCell(r, c);
  1241.         ++c;
  1242.         if (c > fClipDocument->fNoOfColumns)
  1243.         {
  1244.             c = 1;
  1245.             ++r;
  1246.             if (r > fClipDocument->fNoOfRows)
  1247.                 r = 1;
  1248.         }
  1249.         
  1250.         destCell->CopyContents(sourceCell);            // copy the necessary fields 
  1251.     }
  1252.     this->UpdateViews();
  1253. } // TCellPasteCommand::RedoIt 
  1254.  
  1255.  
  1256. //----------------------------------------------------------------------------------------
  1257. // TCellPasteCommand::UpdateViews: 
  1258. //----------------------------------------------------------------------------------------
  1259. #pragma segment ADoCommand
  1260.  
  1261. void TCellPasteCommand::UpdateViews()
  1262.  
  1263. {
  1264.     CStr255        aString;
  1265.     GridCell    aCell;
  1266.  
  1267.     fCalcDocument->DoRecalculate(!kForceAutomatic, kUpdateDependencies);
  1268.     fCalcDocument->fCellsView->InvalidateSelection();
  1269.  
  1270.     aCell.h = fCalcDocument->fEditColumn;
  1271.     aCell.v = fCalcDocument->fEditRow;
  1272.     if (fCalcDocument->fCellsView->IsCellSelected(aCell))
  1273.     {
  1274.         fCalcDocument->fEditCell = fCalcDocument->GetCell(aCell.v, aCell.h);
  1275.         fCalcDocument->fEditCell->GetAsString(aString);
  1276.         fCalcDocument->fEntryView->SetToString(aString);
  1277.     }
  1278. } // TCellPasteCommand::UpdateViews 
  1279.  
  1280.  
  1281.  
  1282. //========================================================================================
  1283. // CLASS CCalcCellIterator
  1284. //========================================================================================
  1285. #undef Inherited
  1286.  
  1287. //----------------------------------------------------------------------------------------
  1288. // CCalcCellIterator::CCalcCellIterator: 
  1289. //----------------------------------------------------------------------------------------
  1290. #pragma segment IteratorRes
  1291.  
  1292. CCalcCellIterator::CCalcCellIterator(TCalcDocument* theCalcDocument) :
  1293.     CObjectIterator(theCalcDocument ? theCalcDocument->fCells : NULL)
  1294. {
  1295. } // CCalcCellIterator::CCalcCellIterator 
  1296.  
  1297.  
  1298. //----------------------------------------------------------------------------------------
  1299. // CCalcCellIterator::CCalcCellIterator: 
  1300. //----------------------------------------------------------------------------------------
  1301. #pragma segment IteratorRes
  1302.  
  1303. CCalcCellIterator::CCalcCellIterator(TCellList* theCellList) :
  1304.     CObjectIterator(theCellList)
  1305. {
  1306. } // CCalcCellIterator::CCalcCellIterator 
  1307.  
  1308.  
  1309. //----------------------------------------------------------------------------------------
  1310. // CCalcCellIterator::~CCalcCellIterator: 
  1311. //----------------------------------------------------------------------------------------
  1312. #pragma segment IteratorRes
  1313.  
  1314. CCalcCellIterator::~CCalcCellIterator()
  1315. {
  1316. } // CCalcCellIterator::~CCalcCellIterator 
  1317.  
  1318.  
  1319. //----------------------------------------------------------------------------------------
  1320. // CCalcCellIterator::CurrentCell: 
  1321. //----------------------------------------------------------------------------------------
  1322. #pragma segment IteratorRes
  1323.  
  1324. TCell* CCalcCellIterator::CurrentCell()
  1325. {
  1326.     // returns the current Cell
  1327.     return (TCell *)this->CurrentObject();
  1328. } // CCalcCellIterator::CurrentCell 
  1329.  
  1330.  
  1331. //----------------------------------------------------------------------------------------
  1332. // CCalcCellIterator::FirstCell: 
  1333. //----------------------------------------------------------------------------------------
  1334. #pragma segment IteratorRes
  1335.  
  1336. TCell* CCalcCellIterator::FirstCell()
  1337. {
  1338.     // return the first Cell in the iteration
  1339.     return (TCell *)this->FirstObject();
  1340. } // CCalcCellIterator::FirstCell 
  1341.  
  1342.  
  1343. //----------------------------------------------------------------------------------------
  1344. // CCalcCellIterator::NextCell: 
  1345. //----------------------------------------------------------------------------------------
  1346. #pragma segment IteratorRes
  1347.  
  1348. TCell* CCalcCellIterator::NextCell()
  1349. {
  1350.     // advances the iteration and then returns the Cell
  1351.     return (TCell *)this->NextObject();
  1352. } // CCalcCellIterator::NextCell 
  1353.  
  1354.  
  1355. //========================================================================================
  1356. // CLASS CSelectedExistingCalcCellIterator
  1357. //========================================================================================
  1358. #undef Inherited
  1359.  
  1360. //----------------------------------------------------------------------------------------
  1361. // CSelectedExistingCalcCellIterator::CSelectedExistingCalcCellIterator: 
  1362. //----------------------------------------------------------------------------------------
  1363. #pragma segment IteratorRes
  1364.  
  1365. CSelectedExistingCalcCellIterator::CSelectedExistingCalcCellIterator(TCalcDocument* theCalcDocument) :
  1366.     CCalcCellIterator(theCalcDocument)
  1367. {
  1368.     fSelectedRegion = theCalcDocument->fCellsView->fSelections;
  1369. } // CSelectedExistingCalcCellIterator::CSelectedExistingCalcCellIterator 
  1370.  
  1371.  
  1372. //----------------------------------------------------------------------------------------
  1373. // CSelectedExistingCalcCellIterator::~CSelectedExistingCalcCellIterator: 
  1374. //----------------------------------------------------------------------------------------
  1375. #pragma segment IteratorRes
  1376.  
  1377. CSelectedExistingCalcCellIterator::~CSelectedExistingCalcCellIterator()
  1378. {
  1379. } // CSelectedExistingCalcCellIterator::~CSelectedExistingCalcCellIterator 
  1380.  
  1381.  
  1382. //----------------------------------------------------------------------------------------
  1383. // CSelectedExistingCalcCellIterator::Reset: 
  1384. //----------------------------------------------------------------------------------------
  1385. #pragma segment IteratorRes
  1386.  
  1387. void CSelectedExistingCalcCellIterator::Reset()
  1388. {
  1389.     CArrayIterator::Reset();                                    // this should be Inherited::Reset,
  1390.                                                                 // but we can't since it's a C++ object.
  1391.     if (this->More() &&!this->IsCellSelected(CurrentCell()))    // check that the first cell meets the
  1392.                                                                 // criteria for acceptance
  1393.         this->Advance();                                        // It doesn't, so we'll get the next 
  1394.                                                                 // one, which is guaranteed to either
  1395.                                                                 // meet the criteria, or be NULL
  1396. } // CSelectedExistingCalcCellIterator::Reset 
  1397.  
  1398.  
  1399. //----------------------------------------------------------------------------------------
  1400. // CSelectedExistingCalcCellIterator::Advance: 
  1401. //----------------------------------------------------------------------------------------
  1402. #pragma segment IteratorRes
  1403.  
  1404. void CSelectedExistingCalcCellIterator::Advance()
  1405. {
  1406.     CArrayIterator::Advance();                                    // this should be Inherited::Advance,
  1407.                                                                 // but we can't since it's a C++ object.
  1408.     while (this->More() &&!this->IsCellSelected(CurrentCell()))
  1409.         //while it doesn't meet the criteria…
  1410.         CArrayIterator::Advance();                                // Get the next one.  
  1411.                                                                 // (this should also be "inherited".)
  1412. } // CSelectedExistingCalcCellIterator::Advance 
  1413.  
  1414.  
  1415. //----------------------------------------------------------------------------------------
  1416. // CSelectedExistingCalcCellIterator::IsCellSelected: 
  1417. //----------------------------------------------------------------------------------------
  1418. #pragma segment IteratorRes
  1419.  
  1420. Boolean CSelectedExistingCalcCellIterator::IsCellSelected(TCell* theCell)
  1421.  
  1422. {
  1423.     if (this->More())                                                // is the cell valid??
  1424.         return PtInRgn(theCell->GetCoordinates(), fSelectedRegion);    // is it selected?
  1425.     else
  1426.         return FALSE;                                                // there is no cell, so it's
  1427.                                                                     // obviously not selected.
  1428. } // CSelectedExistingCalcCellIterator::IsCellSelected 
  1429.  
  1430.  
  1431. //========================================================================================
  1432. // CLASS CExistingCalcCellIterator
  1433. //========================================================================================
  1434. #undef Inherited
  1435.  
  1436. //----------------------------------------------------------------------------------------
  1437. // CExistingCalcCellIterator::CExistingCalcCellIterator: 
  1438. //----------------------------------------------------------------------------------------
  1439. #pragma segment IteratorRes
  1440.  
  1441. CExistingCalcCellIterator::CExistingCalcCellIterator(TCalcDocument* theCalcDocument) :
  1442.     CCalcCellIterator(theCalcDocument)
  1443.  
  1444. {
  1445.     fCalcDocument = theCalcDocument;
  1446. } // CExistingCalcCellIterator::CExistingCalcCellIterator 
  1447.  
  1448.  
  1449. //----------------------------------------------------------------------------------------
  1450. // CExistingCalcCellIterator::~CExistingCalcCellIterator: 
  1451. //----------------------------------------------------------------------------------------
  1452. #pragma segment IteratorRes
  1453.  
  1454. CExistingCalcCellIterator::~CExistingCalcCellIterator()
  1455. {
  1456. } // CExistingCalcCellIterator::~CExistingCalcCellIterator 
  1457.  
  1458.  
  1459. //----------------------------------------------------------------------------------------
  1460. // CExistingCalcCellIterator::Reset: 
  1461. //----------------------------------------------------------------------------------------
  1462. #pragma segment IteratorRes
  1463.  
  1464. void CExistingCalcCellIterator::Reset()
  1465. {
  1466.     CArrayIterator::Reset();                    // this should be Inherited::Reset, 
  1467.                                                 // but we can't since it's a C++ object.
  1468.                                                 // if you agree with me, please ask Bjarne
  1469.                                                 // to change the standard.
  1470.  
  1471.     // now check that the first cell meets the criteria for acceptance
  1472.     if (this->More() &&!this->CellExists())
  1473.  
  1474.         this->Advance();                        // It doesn't, so we'll get the next one, 
  1475.                                                 // which is guaranteed to either meet the
  1476.                                                 // criteria, or be NULL
  1477. } // CExistingCalcCellIterator::Reset 
  1478.  
  1479.  
  1480. //----------------------------------------------------------------------------------------
  1481. // CExistingCalcCellIterator::CellExists: 
  1482. //----------------------------------------------------------------------------------------
  1483. #pragma segment IteratorRes
  1484.  
  1485. Boolean CExistingCalcCellIterator::CellExists()
  1486.  
  1487. {
  1488.     if (this->More())                                    // is the cell valid??
  1489.     {
  1490.         TCell * theCell = this->CurrentCell();
  1491.         return fCalcDocument->IsExistingCell(theCell);    // is it selected?
  1492.     }
  1493.     else
  1494.         return FALSE;                                    // there is no cell, so it's obviously 
  1495.                                                         // not selected.
  1496. } // CExistingCalcCellIterator::CellExists 
  1497.  
  1498.  
  1499. //----------------------------------------------------------------------------------------
  1500. // CExistingCalcCellIterator::Advance: 
  1501. //----------------------------------------------------------------------------------------
  1502. #pragma segment IteratorRes
  1503.  
  1504. void CExistingCalcCellIterator::Advance()
  1505. {
  1506.     CArrayIterator::Advance();                        // this should be Inherited::Advance, 
  1507.                                                     // but we can't since it's a C++ object.
  1508.     while (this->More() &&!this->CellExists())
  1509.         //while it doesn't meet the criteria…
  1510.         CArrayIterator::Advance();                    // Get the next one.  
  1511.                                                     // (this should also be "inherited".)
  1512. } // CExistingCalcCellIterator::Advance 
  1513.  
  1514.  
  1515. //========================================================================================
  1516. // CLASS CReferencedCellIterator
  1517. //========================================================================================
  1518. #undef Inherited
  1519.  
  1520. //----------------------------------------------------------------------------------------
  1521. // CReferencedCellIterator::CReferencedCellIterator: 
  1522. //----------------------------------------------------------------------------------------
  1523. #pragma segment IteratorRes
  1524.  
  1525. CReferencedCellIterator::CReferencedCellIterator(TCell* theCell) :
  1526.     CNotifierIterator(theCell,(TStandardDependencySpace*) theCell->GetDependencySpace())
  1527. {
  1528. } // CReferencedCellIterator::CReferencedCellIterator 
  1529.  
  1530.  
  1531. //----------------------------------------------------------------------------------------
  1532. // CReferencedCellIterator::~CReferencedCellIterator: 
  1533. //----------------------------------------------------------------------------------------
  1534. #pragma segment IteratorRes
  1535.  
  1536. CReferencedCellIterator::~CReferencedCellIterator()
  1537. {
  1538. } // CReferencedCellIterator::~CReferencedCellIterator 
  1539.  
  1540.  
  1541. //----------------------------------------------------------------------------------------
  1542. // CReferencedCellIterator::Reset: 
  1543. //----------------------------------------------------------------------------------------
  1544. #pragma segment IteratorRes
  1545.  
  1546. void CReferencedCellIterator::Reset()
  1547. {
  1548.     CNotifierIterator::Reset();                        // this should be Inherited::Reset, 
  1549.                                                     // but we can't since it's a C++ object.
  1550.  
  1551.     // now check that the first notifier is a cell
  1552.     if (this->More() &&!this->NotifierIsCell())
  1553.  
  1554.         this->Advance();                        // It doesn't, so we'll get the next one, 
  1555.                                                 // which is guaranteed to either meet the
  1556.                                                 // criteria, or be NULL
  1557. } // CReferencedCellIterator::Reset 
  1558.  
  1559.  
  1560. //----------------------------------------------------------------------------------------
  1561. // CReferencedCellIterator::FirstCell: 
  1562. //----------------------------------------------------------------------------------------
  1563. #pragma segment IteratorRes
  1564.  
  1565. TCell* CReferencedCellIterator::FirstCell()
  1566. {
  1567.     return (TCell *)this->FirstNotifier();
  1568. } // CReferencedCellIterator::FirstCell 
  1569.  
  1570.  
  1571. //----------------------------------------------------------------------------------------
  1572. // CReferencedCellIterator::CurrentCell: 
  1573. //----------------------------------------------------------------------------------------
  1574. #pragma segment IteratorRes
  1575.  
  1576. TCell* CReferencedCellIterator::CurrentCell()
  1577. {
  1578.     return (TCell *)this->CurrentNotifier();
  1579. } // CReferencedCellIterator::CurrentCell 
  1580.  
  1581.  
  1582. //----------------------------------------------------------------------------------------
  1583. // CReferencedCellIterator::NextCell: 
  1584. //----------------------------------------------------------------------------------------
  1585. #pragma segment IteratorRes
  1586.  
  1587. TCell* CReferencedCellIterator::NextCell()
  1588. {
  1589.     return (TCell *)this->NextNotifier();
  1590. } // CReferencedCellIterator::NextCell 
  1591.  
  1592.  
  1593. //----------------------------------------------------------------------------------------
  1594. // CReferencedCellIterator::NotifierIsCell: 
  1595. //----------------------------------------------------------------------------------------
  1596. #pragma segment IteratorRes
  1597.  
  1598. Boolean CReferencedCellIterator::NotifierIsCell()
  1599. {
  1600.     if (this->More())        // is the notifier valid??
  1601.     {
  1602.         TObject * theObject = this->CurrentNotifier();
  1603.         return theObject->DescendsFrom(TCell::GetClassDescStatic());    // is it a cell?
  1604.     }
  1605.     else
  1606.         return FALSE;                            // there is no notifier, so it's obviously 
  1607.                                                 // not a cell.
  1608. } // CReferencedCellIterator::NotifierIsCell 
  1609.  
  1610.  
  1611. //----------------------------------------------------------------------------------------
  1612. // CReferencedCellIterator::Advance: 
  1613. //----------------------------------------------------------------------------------------
  1614. #pragma segment IteratorRes
  1615.  
  1616. void CReferencedCellIterator::Advance()
  1617. {
  1618.     CNotifierIterator::Advance();                    // this should be Inherited::Advance, but 
  1619.                                                     // we can't since it's a C++ object.
  1620.     while (this->More() &&!this->NotifierIsCell())    // while it doesn't meet the criteria…
  1621.         CNotifierIterator::Advance();                // Get the next one.  (this should also 
  1622.                                                     // be "inherited".)
  1623. } // CReferencedCellIterator::Advance 
  1624.  
  1625.  
  1626. //========================================================================================
  1627. // CLASS CDependentCellIterator
  1628. //========================================================================================
  1629. #undef Inherited
  1630.  
  1631. //----------------------------------------------------------------------------------------
  1632. // CDependentCellIterator::CDependentCellIterator: 
  1633. //----------------------------------------------------------------------------------------
  1634. #pragma segment IteratorRes
  1635.  
  1636. CDependentCellIterator::CDependentCellIterator(TCell* theCell) :
  1637.     CDependentIterator(theCell,(TStandardDependencySpace*) theCell->GetDependencySpace())
  1638. {
  1639. } // CDependentCellIterator::CDependentCellIterator 
  1640.  
  1641.  
  1642. //----------------------------------------------------------------------------------------
  1643. // CDependentCellIterator::~CDependentCellIterator: 
  1644. //----------------------------------------------------------------------------------------
  1645. #pragma segment IteratorRes
  1646.  
  1647. CDependentCellIterator::~CDependentCellIterator()
  1648. {
  1649. } // CDependentCellIterator::~CDependentCellIterator 
  1650.  
  1651.  
  1652. //----------------------------------------------------------------------------------------
  1653. // CDependentCellIterator::Reset: 
  1654. //----------------------------------------------------------------------------------------
  1655. #pragma segment IteratorRes
  1656.  
  1657. void CDependentCellIterator::Reset()
  1658. {
  1659.     CDependentIterator::Reset();                    // this should be Inherited::Reset, but 
  1660.                                                     // we can't since it's a C++ object.
  1661.  
  1662.     // now check that the first notifier is a cell
  1663.     if (this->More() &&!this->DependentIsCell())
  1664.         this->Advance();                            // It isn't, so we'll get the next one, 
  1665.                                                     // which is guaranteed to either meet the
  1666.                                                     // criteria, or be NULL
  1667. } // CDependentCellIterator::Reset 
  1668.  
  1669.  
  1670. //----------------------------------------------------------------------------------------
  1671. // CDependentCellIterator::FirstCell: 
  1672. //----------------------------------------------------------------------------------------
  1673. #pragma segment IteratorRes
  1674.  
  1675. TCell* CDependentCellIterator::FirstCell()
  1676. {
  1677.     return (TCell *)this->FirstDependent();
  1678. } // CDependentCellIterator::FirstCell 
  1679.  
  1680.  
  1681. //----------------------------------------------------------------------------------------
  1682. // CDependentCellIterator::CurrentCell: 
  1683. //----------------------------------------------------------------------------------------
  1684. #pragma segment IteratorRes
  1685.  
  1686. TCell* CDependentCellIterator::CurrentCell()
  1687. {
  1688.     return (TCell *)this->CurrentDependent();
  1689. } // CDependentCellIterator::CurrentCell 
  1690.  
  1691.  
  1692. //----------------------------------------------------------------------------------------
  1693. // CDependentCellIterator::NextCell: 
  1694. //----------------------------------------------------------------------------------------
  1695. #pragma segment IteratorRes
  1696.  
  1697. TCell* CDependentCellIterator::NextCell()
  1698. {
  1699.     return (TCell *)this->NextDependent();
  1700. } // CDependentCellIterator::NextCell 
  1701.  
  1702.  
  1703. //----------------------------------------------------------------------------------------
  1704. // CDependentCellIterator::DependentIsCell: 
  1705. //----------------------------------------------------------------------------------------
  1706. #pragma segment IteratorRes
  1707.  
  1708. Boolean CDependentCellIterator::DependentIsCell()
  1709. {
  1710.     if (this->More())                            // is the dependent valid??
  1711.     {
  1712.         TObject * theObject = this->CurrentDependent();
  1713.         return theObject->DescendsFrom(TCell::GetClassDescStatic());    // is it a cell?
  1714.     }
  1715.     else
  1716.         return FALSE;                            // there is no dependent, so it's obviously not a cell.
  1717. } // CDependentCellIterator::DependentIsCell 
  1718.  
  1719.  
  1720. //----------------------------------------------------------------------------------------
  1721. // CDependentCellIterator::Advance: 
  1722. //----------------------------------------------------------------------------------------
  1723. #pragma segment IteratorRes
  1724.  
  1725. void CDependentCellIterator::Advance()
  1726. {
  1727.     CDependentIterator::Advance();                    // this should be Inherited::Advance, 
  1728.                                                     // but we can't since it's a C++ object.
  1729.     while (this->More() &&!this->DependentIsCell())    // while it doesn't meet the criteria…
  1730.         CDependentIterator::Advance();                // Get the next one.  (this should also 
  1731.                                                     // be "inherited".)
  1732. } // CDependentCellIterator::Advance 
  1733.  
  1734. //========================================================================================
  1735. // CLASS CParseSubscribedText
  1736. //========================================================================================
  1737. #undef Inherited
  1738.  
  1739. //----------------------------------------------------------------------------------------
  1740. // CParseSubscribedText::CParseSubscribedText: 
  1741. //----------------------------------------------------------------------------------------
  1742. #pragma segment ANonRes
  1743.  
  1744. CParseSubscribedText::CParseSubscribedText(TDesignator*    aDesignator,
  1745.                                            TStream*        aStream,
  1746.                                            long            length,
  1747.                                            CRect        aSubBounds,    // bounds of the subscriber 
  1748.                                            CRect        aPubBounds)    // bounds of the publisher 
  1749. {
  1750.     theDesignator = aDesignator;
  1751.     theStream = aStream;
  1752.     theLength = length;
  1753.     subBounds = aSubBounds;
  1754.     pubBounds = aPubBounds;
  1755. } // CParseSubscribedText::CParseSubscribedText 
  1756.  
  1757.  
  1758. //----------------------------------------------------------------------------------------
  1759. // CParseSubscribedText::ParseSubscribedText: 
  1760. //----------------------------------------------------------------------------------------
  1761. #pragma segment ANonRes
  1762. // same as its caller DoReadTEXT
  1763.  
  1764. CStr255 CParseSubscribedText::ParseSubscribedText(Handle textHdl, GridCell    aGridCell)
  1765.  
  1766. {
  1767.     short    i;                                    // just an ordinary index.
  1768.     CStr255    ParseSubscribedTextResult;            // the temporary of the return result
  1769.  
  1770.     theText = textHdl;
  1771.     if (theLength == 0)
  1772.     {
  1773.         return ParseSubscribedTextResult;
  1774.     }
  1775.     else
  1776.     {
  1777.         normalizedCell.v = aGridCell.v - subBounds.top;
  1778.         normalizedCell.h = aGridCell.h - subBounds.left;
  1779.         offset = 0;
  1780.  
  1781.         // skip over returns 
  1782.         for (i = 1; i <= normalizedCell.v; i++)
  1783.         {
  1784.             this->ScanTo(chReturn);
  1785.             offset = offset + 1;                // skip over return 
  1786.             if (offset > theLength)                // there's no more input 
  1787.                 return ParseSubscribedTextResult;
  1788.         }
  1789.  
  1790.         // is there a relevant data item to read in? 
  1791.         if (this->NumTabs() < normalizedCell.h)
  1792.             return ParseSubscribedTextResult;
  1793.  
  1794.         // skip over tabs 
  1795.         for (i = 1; i <= normalizedCell.h; i++)
  1796.         {
  1797.             this->ScanTo(chTab);
  1798.             offset = offset + 1;                // skip over tab 
  1799.             if (offset > theLength)                // there's no more input 
  1800.                 return ParseSubscribedTextResult;
  1801.         }
  1802.  
  1803.         p = (unsigned char*)(*theText) + offset;    // set where to start
  1804.         maxLength = Min(theLength - offset, 255);
  1805.         offset = 0;
  1806.         aChar = *(p + offset);                        // get the "offset"th character
  1807.  
  1808.         ParseSubscribedTextResult = "";
  1809.         
  1810.         while (((offset < maxLength) && (aChar != chTab) && (aChar != chReturn)))
  1811.         {
  1812.             offset = offset + 1;
  1813.             ParseSubscribedTextResult += aChar;                // save the current character
  1814.             aChar = *(p + offset);                            // get the next one
  1815.         }
  1816.         return ParseSubscribedTextResult;
  1817.     }
  1818. } // CParseSubscribedText::ParseSubscribedText 
  1819.  
  1820.  
  1821. //----------------------------------------------------------------------------------------
  1822. // CParseSubscribedText::ScanTo: 
  1823. //----------------------------------------------------------------------------------------
  1824. #pragma segment ANonRes
  1825.  
  1826. void CParseSubscribedText::ScanTo(char ch)
  1827.  
  1828. {
  1829.     unsigned char* p;
  1830.  
  1831.  
  1832.     p = (unsigned char*)(*theText) + offset;
  1833.     while ((*p != ch) && (offset < theLength))
  1834.     {
  1835.         offset = offset + 1;
  1836.         p = (unsigned char*)(*theText) + offset;
  1837.     }
  1838. } // CParseSubscribedText::ScanTo 
  1839.  
  1840.  
  1841. //----------------------------------------------------------------------------------------
  1842. // CParseSubscribedText::NumTabs: 
  1843. //----------------------------------------------------------------------------------------
  1844. #pragma segment ANonRes
  1845.  
  1846. short CParseSubscribedText::NumTabs()
  1847. // number of tabs between *theText + localOffset and the next chReturn 
  1848.  
  1849. {
  1850.     unsigned char* p;
  1851.     long localOffset;
  1852.     short num;
  1853.  
  1854.  
  1855.     localOffset = offset;
  1856.     num = 0;
  1857.     p = (unsigned char*)(*theText) + localOffset;
  1858.     while ((*p != chReturn) && (localOffset < theLength))
  1859.     {
  1860.         if (*p == chTab)
  1861.             num = num + 1;
  1862.         localOffset = localOffset + 1;
  1863.         p = (unsigned char*)(*theText) + localOffset;
  1864.     }
  1865.     return num;
  1866. } // CParseSubscribedText::NumTabs 
  1867.  
  1868.  
  1869. //========================================================================================
  1870. // CLASS CCellParser
  1871. //========================================================================================
  1872. #undef Inherited
  1873.  
  1874. //----------------------------------------------------------------------------------------
  1875. // CCellParser::CCellParser: 
  1876. //----------------------------------------------------------------------------------------
  1877. #pragma segment ARes
  1878. // same as its callers TCell:DoUpdate and TCell::Recalculate
  1879.  
  1880. CCellParser::CCellParser(TCell* theCell)
  1881. {
  1882.     fCell = theCell;
  1883.     fCalcDocument = fCell->fCalcDocument;
  1884. } // CCellParser::CCellParser 
  1885.  
  1886.  
  1887. //----------------------------------------------------------------------------------------
  1888. // CCellParser::GetNextChar: 
  1889. //----------------------------------------------------------------------------------------
  1890. #pragma segment ARes
  1891. void CCellParser::GetNextChar()
  1892.  
  1893. {
  1894.     do
  1895.     {
  1896.         if (formulaIndex < formulaLength)
  1897.         {
  1898.             ++formulaIndex;
  1899.             theChar = fFormula[formulaIndex];    // get the "formulaIndex"th character of fFormula
  1900.         }
  1901.         else
  1902.             theChar = 0;
  1903.  
  1904.     } while (theChar == ' ');
  1905.     if ((theChar >= 'a') && (theChar <= 'z'))
  1906.         theChar = theChar - 32;
  1907. } // CCellParser::GetNextChar 
  1908.  
  1909.  
  1910. //----------------------------------------------------------------------------------------
  1911. // CCellParser::DoInteger: 
  1912. //----------------------------------------------------------------------------------------
  1913. #pragma segment ARes
  1914.  
  1915. EvalResult CCellParser::DoInteger(short& theInteger)
  1916. {
  1917.     theInteger = 0;
  1918.     while (IsDigit(theChar))
  1919.     {
  1920.         theInteger = theInteger * 10 + theChar - '0';
  1921.         this->GetNextChar();
  1922.     }
  1923.     return kNoError;
  1924. } // CCellParser::DoInteger 
  1925.  
  1926.  
  1927. //----------------------------------------------------------------------------------------
  1928. // CCellParser::DoNumber: 
  1929. //----------------------------------------------------------------------------------------
  1930. #pragma segment ARes
  1931.  
  1932. EvalResult CCellParser::DoNumber(ValueType& theValue)
  1933.  
  1934. {
  1935.     // DoNumber is called only when theChar is a numeric digit or a decimal CPoint 
  1936.     short    newIndex;
  1937.     decimal    decimalNumber;
  1938.     short    IsValidNumber = FALSE;                // this is because it is passed in as a
  1939.                                                 // reference in str2dec and str2dec's
  1940.                                                 // interface is dumb and requires a
  1941.                                                 // reference to a short.
  1942.     Boolean    startsWithDecPt;
  1943.  
  1944.  
  1945.     startsWithDecPt = (theChar == '.');
  1946.     newIndex = formulaIndex -1;
  1947.     
  1948.     str2dec((const char*)fFormula, &newIndex, &decimalNumber, &IsValidNumber);
  1949.     // Str2Dec returns IsValidNumber == false if the digits are followed by non-numerics like * 
  1950.  
  1951.     if (startsWithDecPt && (!IsValidNumber))
  1952.     {
  1953.         this->GetNextChar();
  1954.         if (!IsDigit(theChar))
  1955.             return kBadNumber;
  1956.     }
  1957.     formulaIndex = newIndex;
  1958.     this->GetNextChar();
  1959.     theValue = dec2num(&decimalNumber);
  1960.     return kNoError;
  1961. } // CCellParser::DoNumber 
  1962.  
  1963.  
  1964. //----------------------------------------------------------------------------------------
  1965. // CCellParser::DoCellReference: 
  1966. //----------------------------------------------------------------------------------------
  1967. #pragma segment ARes
  1968.  
  1969. EvalResult CCellParser::DoCellReference(ValueType& theValue)
  1970.  
  1971. {
  1972.     EvalResult    theResult;
  1973.     short        r;                                    // Can't use RowNumber because it may be 
  1974.     short        c;                                    // …out of range 
  1975.     TCell *        referencedCell;
  1976.     CRect        aRect;
  1977.  
  1978.     theResult = kNoError;
  1979.     aRect = fCalcDocument->fDimensions;            // valid coordinates 
  1980.     c = 0;
  1981.     while ((theChar >= 'A') && (theChar <= 'Z') && (c <= aRect.right))
  1982.     {
  1983.         c = c * 26 + theChar - 'A' + 1;
  1984.         this->GetNextChar();
  1985.     }
  1986.     if (c > aRect.right)                        // column is out of range, so 
  1987.         r = 0;                                    // …don't bother looking for row number 
  1988.     else
  1989.         theResult = this->DoInteger(r);
  1990.     if (fCalcDocument->CellInRange(r, c, aRect))
  1991.     {
  1992.         referencedCell = fCalcDocument->GetExistingCell(r - fCalcDocument->fRowOffset, c - fCalcDocument->fColumnOffset);
  1993.         if (referencedCell == NULL)                // cell doesn't exist 
  1994.             theValue = 0;
  1995.         else
  1996.         {
  1997.             if (referencedCell->fEvaluating)
  1998.                 theResult = kSelfReference;
  1999.             else if (referencedCell->fKind == kErrorCell)
  2000.                 theResult = kErrorCellReference;
  2001.             else if (referencedCell->fKind == kTextCell)
  2002.                 theValue = 0;
  2003.             else
  2004.                 theValue = referencedCell->fValue;
  2005.  
  2006.             if (updateDependencies &&            /*!!!RCR*/(theResult != kSelfReference))
  2007.             {
  2008.                 referencedCell->AddDependentCell(fCell);
  2009.             }
  2010.         }
  2011.     }
  2012.     else
  2013.         theResult = kBadCellReference;
  2014.     return theResult;
  2015. } // CCellParser::DoCellReference 
  2016.  
  2017.  
  2018. //----------------------------------------------------------------------------------------
  2019. // CCellParser::Term: 
  2020. //----------------------------------------------------------------------------------------
  2021. #pragma segment ARes
  2022.  
  2023. EvalResult CCellParser::Term(ValueType& theValue)
  2024.  
  2025. {
  2026.     EvalResult theTempResult;
  2027.  
  2028.     if (theChar == '(')
  2029.     {
  2030.         this->GetNextChar();
  2031.         theTempResult = this->Expression(theValue);
  2032.         if (theChar == ')')
  2033.             this->GetNextChar();
  2034.         else
  2035.             theTempResult = kMissingRightParen;
  2036.     }
  2037.     else if (IsDigit(theChar) || (theChar == '.'))
  2038.         theTempResult = this->DoNumber(theValue);
  2039.     else if ((theChar >= 'A') && (theChar <= 'Z'))
  2040.         theTempResult = this->DoCellReference(theValue);
  2041.     else if (theChar == '+')
  2042.     {
  2043.         this->GetNextChar();
  2044.         theTempResult = this->Term(theValue);
  2045.     }
  2046.     else if (theChar == '-')
  2047.     {
  2048.         this->GetNextChar();
  2049.         theTempResult = this->Term(theValue);
  2050.         theValue = -theValue;
  2051.     }
  2052.     else
  2053.         theTempResult = kIllegalCharacter;
  2054.     return theTempResult;
  2055. } // CCellParser::Term 
  2056.  
  2057.  
  2058. //----------------------------------------------------------------------------------------
  2059. // CCellParser::Factor: 
  2060. //----------------------------------------------------------------------------------------
  2061. #pragma segment ARes
  2062.  
  2063. EvalResult CCellParser::Factor(ValueType& theValue)
  2064.  
  2065. {
  2066.     EvalResult    theResult;
  2067.     ValueType    factorValue;
  2068.  
  2069.  
  2070.     theResult = this->Term(theValue);
  2071.     if (theResult == kNoError)
  2072.         if (theChar == '*')
  2073.         {
  2074.             this->GetNextChar();
  2075.             theResult = this->Factor(factorValue);
  2076.             theValue = theValue * factorValue;
  2077.         }
  2078.         else if (theChar == '/')
  2079.         {
  2080.             this->GetNextChar();
  2081.             theResult = this->Factor(factorValue);
  2082.             theValue = theValue / factorValue;
  2083.         }
  2084.     return theResult;
  2085. } // CCellParser::Factor 
  2086.  
  2087.  
  2088. //----------------------------------------------------------------------------------------
  2089. // CCellParser::Expression: 
  2090. //----------------------------------------------------------------------------------------
  2091. #pragma segment ARes
  2092.  
  2093. EvalResult CCellParser::Expression(ValueType& theValue)
  2094.  
  2095. {
  2096.     EvalResult    factorResult;
  2097.     ValueType    factorValue;
  2098.  
  2099.  
  2100.     factorResult = this->Factor(theValue);
  2101.     if (factorResult == kNoError)
  2102.         do
  2103.         {
  2104.             if (theChar == '+')
  2105.             {
  2106.                 this->GetNextChar();
  2107.                 factorResult = this->Factor(factorValue);
  2108.                 theValue = theValue + factorValue;
  2109.             }
  2110.             else if (theChar == '-')
  2111.             {
  2112.                 this->GetNextChar();
  2113.                 factorResult = this->Factor(factorValue);
  2114.                 theValue = theValue - factorValue;
  2115.             }
  2116.         } while ((theChar == '+') || (theChar == '-'));
  2117.     return factorResult;
  2118. } // CCellParser::Expression 
  2119.  
  2120.  
  2121. //----------------------------------------------------------------------------------------
  2122. // CCellParser::EvaluateFormula: 
  2123. //----------------------------------------------------------------------------------------
  2124. #pragma segment ARes
  2125.  
  2126. void CCellParser::EvaluateFormula(KindOfCell&    theKind,
  2127.                                   EvalResult&    theError,
  2128.                                   ValueType&    theValue,
  2129.                                   CStr255&        theFormula,
  2130.                                   Boolean        doUpdateDependencies)
  2131. {
  2132.     fFormula = theFormula;
  2133.     updateDependencies = doUpdateDependencies;
  2134.     formulaLength = fFormula.Length();
  2135.     formulaIndex = 0;
  2136.     this->GetNextChar();
  2137.  
  2138.     if (IsDigit(theChar) || (theChar == '=') || (theChar == '-') || (theChar == '+') || (theChar == '.'))
  2139.     {
  2140.         if (theChar == '=')
  2141.             this->GetNextChar();
  2142.  
  2143.         theError = this->Expression(theValue);
  2144.  
  2145.         if (theError == kNoError)
  2146.         {
  2147.             if ((formulaIndex <= formulaLength) && (theChar != 0))
  2148.                 theError = kGarbageAtEnd;
  2149.         }
  2150.         if (theError == kNoError)
  2151.             theKind = kValueCell;
  2152.         else
  2153.             theKind = kErrorCell;
  2154.     }
  2155.     else
  2156.         theKind = kTextCell;
  2157. } // CCellParser::EvaluateFormula 
  2158.  
  2159. //----------------------------------------------------------------------------------------
  2160. // End of UCalcCells.cp
  2161.  
  2162. #pragma segment Inline
  2163.